#include "messagewrapper.h"
#include "MyXmppClient.h"
#include "qmlxmppclient.h"
#include <QDebug>

MessageWrapper::MessageWrapper(QObject *parent) : QObject(parent)
{
    qmlObj = reinterpret_cast<QDeclarativeView*>(parent);
    mlm = NULL;
    mlm = new MsgListModel( this ); //??

    QDeclarativeEngine *engine = qmlObj->engine();
    engine->rootContext()->setContextProperty( "cppListOfMessages", mlm );
}


void MessageWrapper::messageReceived(const QXmppMessage &xmppMsg)
{
    qDebug() << "MessageWrapper::messageReceived(): xmppMsg.type():" << xmppMsg.type();

    if( xmppMsg.state() == QXmppMessage::Active ) {
        this->textMessage(xmppMsg);
    } else if( xmppMsg.state() == QXmppMessage::Inactive ) {
        qDebug() << "QXmppMessage::Inactive";
    } else if( xmppMsg.state() == QXmppMessage::Gone ) {
        qDebug() << "QXmppMessage::Gone";
    } else if( xmppMsg.state() == QXmppMessage::Composing ) {
        this->startWriteMessage(xmppMsg);
    } else if( xmppMsg.state() == QXmppMessage::Paused ) {
        this->pauseWriteMessage(xmppMsg);
    } else {
        this->textMessage(xmppMsg); //????
        qDebug() << "MessageWrapper::messageReceived(): xmppMsg.state():" << xmppMsg.state();
    }
}


void MessageWrapper::textMessage(const QXmppMessage &xmppMsg)
{
    QString id = xmppMsg.id();
    QString msg = xmppMsg.body();
    if( msg.isEmpty() || msg.isNull() ) {
        qDebug() << "Warning! MSG is emty !";
        return;
    }

    MeegimMessage mm;
    mm.dlr = false;
    if( (xmppMsg.stamp().isNull()) || (!xmppMsg.stamp().isValid()) ) {
        mm.date = QDateTime::currentDateTime();
    } else {
        mm.date = xmppMsg.stamp();
    }
    mm.msg = msg;
    mm.id = id;

    QString chatWithJid;
    if ( xmppMsg.from() == MyXmppClient::myJid ) {
        mm.myMsg = true;
        chatWithJid = xmppMsg.to();
    } else {
        mm.myMsg = false;
        chatWithJid = xmppMsg.from();
    }

    QString resource("");
    if( chatWithJid.indexOf('/') >= 0 ) {
        resource = chatWithJid.split('/')[1];
        chatWithJid = chatWithJid.split('/')[0];
    }

    if( ! listOfChats.contains(chatWithJid) )  {
        /* это первое сообщение от этого jid
         * Инициализируем список сообщени для этого jid
         */
        QList<MeegimMessage> *lm = new QList<MeegimMessage>();
        lm->append( mm );
        listOfChats[ chatWithJid ] = lm;
        qDebug() << "new msg: lenList:" << lm->length() << " jid:" << chatWithJid;
        emit openChat( chatWithJid );
    } else {
        QList<MeegimMessage> *lm = listOfChats[ chatWithJid ];
        lm->append( mm );
        listOfChats[ chatWithJid ] = lm;
        qDebug() << "exist msg: lenList:" << lm->length() << " jid:" << chatWithJid;
    }

    qDebug() << "textMessage: listOfChats.contains(" << chatWithJid << "):" << listOfChats.contains(chatWithJid) << " len:" << listOfChats.size();

    QString dataTimeMsg = mm.date.toString("hh:mm:ss");
    MsgItemModel *mim = new MsgItemModel( mm.id, dataTimeMsg, mm.msg, mm.dlr, mm.myMsg, this );
    if( mlm != NULL) {
        mlm->append( mim );
    }


    //TODO:
    /* выполняем вызов ф-ции на QML форме
     * чтобы известить о приходе сообщения
     */
    QMLXmppClient *qmlXmppClient = QMLXmppClient::getInstance();
    if( !qmlXmppClient ) {
        qmlXmppClient->emitMsgRecv( chatWithJid );
    }

    //qDebug() << chatWithJid << " (" << mm.id << ") >" << msg << " " << listOfChats.contains(chatWithJid);
}


void MessageWrapper::initChat( QString jid ) //Q_INVOKABLE
{
    mlm->removeRows( 0, mlm->count() ); //TODO: может takeRows() ???

    qDebug() << "initChat(): " << jid << " listOfChats.contains: " << listOfChats.contains(jid) << " mlm.len:" << mlm->count();

    if( listOfChats.contains(jid) )
    {
        QList<MeegimMessage> *currChat = listOfChats[ jid ];

        QList< MeegimMessage >::const_iterator itr = currChat->begin();
        while ( itr != currChat->end() )
        {
            MeegimMessage m = *itr;
            itr++;

            QString dataTimeMsg = m.date.toString("hh:mm:ss");
            MsgItemModel *mim = new MsgItemModel( m.id, dataTimeMsg, m.msg, m.dlr, m.myMsg, this );
            mlm->append(mim);
        }
    } else {
        QList<MeegimMessage> *lm = new QList<MeegimMessage>();
        listOfChats[ jid ] = lm;
    }

}


void MessageWrapper::startWriteMessage(const QXmppMessage &xmppMsg)
{
    qDebug() << xmppMsg.from() << " writes a message";
}

void MessageWrapper::pauseWriteMessage(const QXmppMessage &xmppMsg)
{
    qDebug() << xmppMsg.from() << " stops a message";
}


void MessageWrapper::messageDelivered( const QString &jid, const QString &id )
{
    QString pureJid = jid.split('/')[0];
    qDebug() << "MessageWrapper::messageDelivered(): " << pureJid << " " << id << " listOfChats.len:" << listOfChats.size() << " jid:" << listOfChats.contains( pureJid );
    if( listOfChats.contains( pureJid ) ) {
        QList<MeegimMessage> *list_mm = listOfChats[ pureJid ];
        QList<MeegimMessage>::iterator itr = list_mm->end(); /* с конца искть нужное сообщ. будет быстрее :) */
        while( itr != list_mm->begin() )
        {
            itr--;
            qDebug() << "DLR*:" << (*itr).id;
            if( (*itr).id == id ) {
                (*itr).dlr = true;
                listOfChats[ pureJid ] = list_mm;
                break;
            }
        }

        MsgItemModel *item = reinterpret_cast<MsgItemModel*>( mlm->find( id ) );
        if( item != 0 ) {
            item->setMsgDlr( true );
        }
    }
}


void MessageWrapper::removeListOfChat( QString &bareJid )
{
    if( listOfChats.contains(bareJid) )  {
        QList<MeegimMessage> *list_mm = listOfChats.take( bareJid );
        if( list_mm != NULL ) {
            delete list_mm;
        }
        qDebug() << "listOfChats.contains("<<bareJid<<"):"<<listOfChats.contains(bareJid);
    }
}


bool MessageWrapper::sendMyMessage(QString bareJid, QString msgBody) //Q_INVOKABLE
{
    QXmppMessage xmppMsg; //???
    xmppMsg.setTo( bareJid );
    xmppMsg.setFrom( MyXmppClient::myJid );
    xmppMsg.setBody( msgBody );

    xmppMsg.setReceiptRequested( true );  /* request DLR */

    //QDateTime currTime = QDateTime::currentDateTime();
    //xmppMsg.setStamp( currTime );

    //QString md5source = currTime.toString( QString("yyyy-MM-ddThh:mm:ss.zzz") ) + bareJid + msgBody;
    //QByteArray hash = QCryptographicHash::hash( md5source.toUtf8(), QCryptographicHash::Md5 );
    //QString msgId = hash.toBase64().data();
    //xmppMsg.setReceiptId( msgId );
    //qDebug() << "xmpp:" << msgId;

    xmppMsg.setState( QXmppMessage::Active );

    emit sendMyMsg( xmppMsg );

    this->messageReceived( xmppMsg );

    return true;
}

